#include<iostream>
using namespace std;

// class A
// {
// public:
// 	A(int a = 0)
// 		: _a(a)
// 	{
// 		cout << "A():" << this << endl;
// 	}

// 	~A()
// 	{
// 		cout << "~A():" << this << endl;
// 	}
// private:
// 	int _a;
// };

// // 结论：不要错配使用，一定匹配使用，否则结果是不确定
// // int main()
// // {
// // 	// 
// // 	A* p1 = new A;
// //     delete p1;
// // 	A* p2 = new A[10];  //44 or 40
// // 	free(p2);
// //     delete[] p2;


// // 	int* p3 = new int[10];  //40
// // 	free(p3);

// // 	return 0;
// // }

// int main()
// {
// 	//A* p1 = new A;
// 	A* p1 = (A*)operator new(sizeof(A));
// 	//p1->A(); // 不支持这样显示调用构造
// 	//new(p1)A;  // 对已有空间，显示调用构造
//     new(p1)A[10]{1,2,3,4};
// 	new(p1)A(10);  // 对已有空间，显示调用构造

// 	//A* p1 = pool.alloc(sizeof(A));
// 	//new(p1)A(10);  // 对已有空间，显示调用构造
	
// 	// delete p1
// 	p1->~A();
// 	operator delete(p1);


// 	// new []
// 	A* p2 = (A*)operator new[](sizeof(A)*10);
// 	//new(p2)A[10]{1,2,3,4};  // 对已有空间，显示调用构造
// 	for (int i = 0; i < 10; ++i)
// 		new(p2 + i)A(i);

// 	// delete[]
// 	for (int i = 0; i < 10; i++)
// 	{
// 		(p2 + i)->~A();
// 	}
// 	operator delete[](p2);

// 	return 0;
// }



/////////////////////////////////////////////////////////////////////////////////////
// typedef int Type ;

// void Swap(Type& left, Type& right)
// {
// 	int temp = left;
// 	left = right;
// 	right = temp;
// }

// void Swap(int& left, int& right)
// {
// 	int temp = left;
// 	left = right;
// 	right = temp;
// }

// void Swap(double& left, double& right)
// {
// 	double temp = left;
// 	left = right;
// 	right = temp;
// }

// // 泛型编程
// // 
// //template<typename T1, typename T2>

// // 模版的原理是什么？需要什么，编译器帮助你实例化你要的函数或者类
// template<typename T>
// void Swap(T& left, T& right)
// {
// 	T temp = left;
// 	left = right;
// 	right = temp;
// }

// int main()
// {
// 	int a = 0, b = 1;
// 	Swap(a, b);

// 	double c = 1.1, d = 2.2;
// 	Swap(c, d);

// 	int* p1 = &a, *p2 = &b;
// 	Swap(p1, p2);

// 	swap(p1, p2);
// 	//...

// 	return 0;
// }



// template<class T>
// template<typename T>
// T Add(const T& left, const T& right)
// {
// 	cout << "T Add(const T& left, const T& right)" << endl;

// 	return left + right;
// }

// template<typename T1, typename T2>
// auto Add(const T1& left, const T2& right)
// {
// 	cout << "auto Add(const T1& left, const T2& right)" << endl;

// 	return left + right;
// }

// int main()
// {
// 	int a1 = 10, a2 = 20;
// 	double d1 = 10.1, d2 = 20.2;
// 	Add(a1, a2);
// 	Add(d1, d2);

// 	cout << Add(a1, (int)d2) << endl;
// 	cout << Add((double)a1, d2) << endl;

// 	// 显示实例化，不再让你去推演参数
// 	cout << Add<int, double> (a1, d2) << endl;
// 	cout << Add<int, double>(a1, d2) << endl;

// 	cout << Add(a1, d2) << endl;
// }




// class A
// {
// public:
// 	A(int a = 0)
// 		: _a(a)
// 	{
// 		cout << "A():" << this << endl;
// 	}

// 	~A()
// 	{
// 		cout << "~A():" << this << endl;
// 	}
// private:
// 	int _a;
// };

// template<class T>
// T* func(int a)
// {
// 	T* p = (T*)operator new(sizeof(T));
// 	new(p)T(a);

// 	return p;
// }

// int main()
// {
// 	int* ret1 = func<int>(1);
// 	A* ret2 = func<A>(1);

// 	return 0;
// }





// // 专门处理int的加法函数
// int Add(int left, int right)
// {
// 	cout << "int Add(int left, int right)" << endl;

// 	return left + right;
// }

// // 通用加法函数
// template<class T1, class T2>
// auto Add(T1 left, T2 right)
// {
// 	cout << "auto Add(T1 left, T2 right)" << endl;

// 	return left + right;
// }

// template<typename T>
// T Add(const T& left, const T& right)
// {
// 	cout << "T Add(const T& left, const T& right)" << endl;

// 	return left + right;
// }

// 
// 1、都有的情况，优先匹配普通函数+参数类型匹配(成品+口味对)
// 2、没有普通函数，优先函数模版+参数类型匹配(半成品+口味对)
// 3、只有一个，类型转换一下也能用，也可以匹配调用(口味不对，将就一下也行)
//void main()
//{
//	Add(1, 2); // 与非函数模板类型完全匹配，不需要函数模板实例化
//	Add(1.1, 2.2); // 与非函数模板类型完全匹配，不需要函数模板实例化
//
//	Add(1, 2.0); // 模板函数可以生成更加匹配的版本，编译器根据实参生成更加匹配的Add函
//}
//





// typedef double DataType;
// struct StackInt
// {
// 	Stack(size_t capacity = 4)
// 	{
// 		_array = (DataType*)malloc(sizeof(DataType) * capacity);
// 		if (nullptr == _array)
// 		{
// 			perror("malloc申请空间失败");
// 			return;
// 		}
// 		_capacity = capacity;
// 		_size = 0;
// 	}

// 	void Push(const DataType& data)
// 	{
// 		// 扩容
// 		_array[_size] = data;
// 		++_size;
// 	}

// 	DataType* _array;
// 	size_t _capacity;
// 	size_t _size;
// };

// int main()
// {
// 	Stack st1; // int
// 	Stack st2; // double


// 	return 0;
// }



// 类模版
template<typename T>
class Stack
{
public:
	Stack(size_t capacity = 4)
	{
		_array = (T*)malloc(sizeof(T) * capacity);
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = capacity;
		_size = 0;
	}

	void Push(const T& data);
private:
	T* _array;
	size_t _capacity;
	size_t _size;
};

// 模版不建议声明和定义分离到.h 和.cpp会出现链接错误，具体原因后面会讲
// 要分离也分离在.h
template<class T>
void Stack<T>::Push(const T& data)
{
	// 扩容
	_array[_size] = data;
	++_size;
}

int main()
{
	Stack<int> st1;    // int
	Stack<double> st2; // double

	return 0;
}

#include<string>
int main()
{
	cout << sizeof(string) << endl;

	return 0;
}